﻿Public Class Registry

    Shared Sub New()
        RegisterExtension(New EchoExtension())


        ''thar be a HACK.  Need some UI or module installer bits to automatically install all of these extensions
        Dim msg As IExtension = System.Reflection.Assembly.Load("DotNetNuke.Light.Server.Extensions").CreateInstance("DotNetNuke.Light.Server.Extensions.MessagingExtension")
        RegisterExtension(msg)

    End Sub

    Private Shared entries As New Light.Common.SharedDictionary(Of System.Guid, IExtension)

    Public Shared Sub RegisterExtension(ByVal Extension As IExtension)
        Using (entries.GetWriteLock())
            entries.Add(Extension.ExtensionID, Extension)
        End Using
    End Sub

    Public Function ProcessRequest(ByVal Request As Light.Common.Request) As Light.Common.Response
        Dim r As New Light.Common.Response
        Dim sc As ServerConnection = GetExtension(Request)
        sc.ServerExtension.ExtensionInstance = Activator.CreateInstance(sc.ServerExtension.ExtensionType)

        sc.ServerExtension.UserInfoProperty.SetValue(sc.ServerExtension.ExtensionInstance, sc.UserInfo, Nothing)

        r.Value = sc.ServerExtension.MethodInstance.Invoke(sc.ServerExtension.ExtensionInstance, Reflection.BindingFlags.InvokeMethod, Nothing, Request.Args, Nothing)
        If (Request.Connection.Credential.UserName <> DotNetNuke.Light.Common.Credential.AnonymousUser) Then r.AuthToken = Crypto.UserInfoToAuthToken(sc.UserInfo)
        Return r
    End Function

    Private Sub LoadUserInfo(ByVal Request As Light.Common.Request, ByVal ServerConnection As ServerConnection)

        If (Request.Connection.Credential.AuthToken Is Nothing) Then
            Dim loginStatus As DotNetNuke.Security.Membership.UserLoginStatus = DotNetNuke.Security.Membership.UserLoginStatus.LOGIN_SUCCESS
            DotNetNuke.Entities.Users.UserController.CheckInsecurePassword(Request.Connection.Credential.UserName, Request.Connection.Credential.Password, loginStatus)
            If Not (loginStatus = DotNetNuke.Security.Membership.UserLoginStatus.LOGIN_SUPERUSER Or loginStatus = DotNetNuke.Security.Membership.UserLoginStatus.LOGIN_SUCCESS) Then
                Throw New Exception("You are not authorized to perform this action." & loginStatus.ToString())
            End If
            ServerConnection.UserInfo = DotNetNuke.Entities.Users.UserController.GetUserByName(Request.Connection.Credential.PortalID, Request.Connection.Credential.UserName)            
        Else
            ServerConnection.UserInfo = Crypto.AuthTokenToUserInfo(Request.Connection.Credential.AuthToken)
        End If
        If (ServerConnection.UserInfo Is Nothing) Then Throw New Exception("Could not find your user for the given Portal ID")

    End Sub

    Public Function GetExtension(ByVal Request As Light.Common.Request) As ServerConnection

        Dim serverConnection As New ServerConnection()
        serverConnection.Credential = Request.Connection.Credential
        serverConnection.Server = Request.Connection.Server

        If (Request.Connection.Credential.UserName <> DotNetNuke.Light.Common.Credential.AnonymousUser) Then
            LoadUserInfo(Request, serverConnection)
        Else
            serverConnection.UserInfo = New DotNetNuke.Entities.Users.UserInfo()
        End If


        Dim ext As IExtension
        Dim sExt As New ServerExtension()
        sExt.MethodName = Request.MethodName

        Using (entries.GetReadLock())
            If Not (entries.ContainsKey(Request.ExtensionID)) Then Throw New Exception("Extension is not registered")
            ext = entries(Request.ExtensionID)
        End Using

        sExt.ExtensionInstance = ext

        sExt.AssemblyInstance = System.Reflection.Assembly.Load(sExt.AssemblyName)
        If (sExt.AssemblyInstance Is Nothing) Then Throw New Exception("Could not resolve assembly reference:" + sExt.AssemblyName)

        sExt.ExtensionType = sExt.AssemblyInstance.GetType(sExt.TypeName)
        If (sExt.ExtensionType Is Nothing) Then Throw New Exception("Could not resolve type reference:" + sExt.TypeName)

        sExt.UserInfoProperty = sExt.ExtensionType.GetProperty("UserInfo")
        If (sExt.UserInfoProperty Is Nothing) Then Throw New Exception("Could not resolve UserInfo Property reference")

        sExt.MethodInstance = sExt.ExtensionType.GetMethod(sExt.MethodName)
        If (sExt.MethodInstance Is Nothing) Then Throw New Exception("Could not resolve method reference:" + sExt.MethodName)


        If Not (Security.Assert(sExt, serverConnection)) Then Throw New Exception("You are not authorized to perform this action")

        serverConnection.ServerExtension = sExt

        Return serverConnection

    End Function


End Class
